package com.ysz.timewheel;

import com.ysz.timewheel.server.struct.ClientStruct;
import com.ysz.timewheel.server.struct.TimeWheelStruct;
import com.ysz.timewheel.server.task.AcceptTask;
import com.ysz.timewheel.server.task.DeactivationTask;
import com.ysz.timewheel.server.task.PollingTask;
import com.ysz.timewheel.server.threadpool.ThreadPool;
import com.ysz.timewheel.server.util.TimeUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;

/**
 * @ClassName TimeWheel
 * @Description 时间轮  解决多客户端注册探活服务
 * @Data 15:21
 * @Version 1.0
 * @Author ysz
 */
public class TimeWheel {

    /**
     * 超时map
     */
    private static final ConcurrentHashMap<Integer, List<ClientStruct>> timeOutTimeClients = new ConcurrentHashMap<>();
    /**
     * 失活map
     */
    private static final ConcurrentHashMap<ClientStruct, Integer> deactivationClientsTime = new ConcurrentHashMap<>();

    /**
     * 启动
     *
     * @author ysz
     * @date 2022/2/23 11:18
     */
    public void start() {
        //开启持续扫描
        this.continueScan();
        //开启处理队列任务
        this.continueProcessQueue();
    }


    /**
     * 注册接口 客户端调用该接口实现长轮训
     *
     * @author ysz
     * @date 2022/2/22 16:20
     */
    public Integer register(ClientStruct clientStruct) {
        //获取当前时刻
        Integer currentSeconds = TimeUtil.getCurrentSeconds();
        //超时map添加
        List<ClientStruct> clientStructs = timeOutTimeClients.putIfAbsent(currentSeconds, new ArrayList<ClientStruct>() {{
            add(clientStruct);
        }});
        if (Objects.nonNull(clientStructs) && clientStructs.size() > 0) {
            clientStructs.add(clientStruct);
        }
        //失活map添加
        deactivationClientsTime.put(clientStruct, currentSeconds);
        //时间轮添加
        TimeWheelStruct.addByIndex(currentSeconds);
        return currentSeconds;
    }


    /**
     * 不断扫描超时map和失活map并将超时或者失活的数据置为失效
     *
     * @author ysz
     * @date 2022/2/22 17:59
     */
    public void continueScan() {
        ExecutorService starterService = ThreadPool.starterService;
        starterService.submit(new PollingTask());
        starterService.submit(new DeactivationTask());
    }


    /**
     * 不断处理队列任务
     *
     * @author ysz
     * @date 2022/2/22 17:59
     */
    public void continueProcessQueue() {
        ExecutorService starterService = ThreadPool.workerService;
        starterService.submit(new AcceptTask());
    }

    public static ConcurrentHashMap<Integer, List<ClientStruct>> getTimeOutTimeClients() {
        return timeOutTimeClients;
    }

    public static ConcurrentHashMap<ClientStruct, Integer> getDeactivationClientsTime() {
        return deactivationClientsTime;
    }
}
